use std::{error::Error, rc::Rc, cell::RefCell};

use super::{ClassReader, ConstantPool, MemberInfo, attribute_info::{self, attr_source_file::SourceFileAttribute, attr_bootstrap_methods::BootstrapMethodsAttribute}, Attribute, EnclosingMethodAttribute};



/*
ClassFile {
    u4             magic; // 魔数
    u2             minor_version; // 次版本号
    u2             major_version; // 主版本好
    u2             constant_pool_count; // 常量池数量
    cp_info        constant_pool[constant_pool_count-1]; // 常量池
    u2             access_flags; // 类访问标志（private public）
    u2             this_class; // 类常量池索引
    u2             super_class; // 超类常量池索引
    u2             interfaces_count; // 接口数量
    u2             interfaces[interfaces_count]; // 接口常量池索引
    u2             fields_count; // 字段数量
    field_info     fields[fields_count]; // 字段
    u2             methods_count; // 方法数量
    method_info    methods[methods_count]; // 方法
    u2             attributes_count; // 数量
    attribute_info attributes[attributes_count]; // 参数
}
*/
#[allow(warnings)]
pub struct ClassFile {
    magic: u32,
    minor_version: u16,
    major_version: u16,
    constant_pool: Option<Rc<RefCell<ConstantPool>>>,
    access_flags: u16,
    this_class: u16,
    super_class: u16,
    interfaces: Vec<u16>,
    fields: Vec<MemberInfo>,
    methods: Vec<MemberInfo>,
    attributes: Vec<Attribute>,
}

impl ClassFile {
    pub fn new() -> ClassFile {
        ClassFile { 
            magic: 0, 
            minor_version: 0, 
            major_version: 0, 
            constant_pool: None, 
            access_flags: 0, 
            this_class: 0, 
            super_class: 0, 
            interfaces: vec![], 
            fields: vec![], 
            methods: vec![], 
            attributes: vec![] 
        }
    }

    // 将class字节解析为ClassFile结构体
    pub fn parse(class_data: Vec<u8>) -> Result<ClassFile, Box<dyn Error>> {
        let mut cr = ClassReader::new(class_data);
        let mut cf = Self::new();
        cf.read(&mut cr);
        Ok(cf)
    }

    // 依次调用方法解析class文件 
    fn read(&mut self, reader: &mut ClassReader) {
        self.read_and_check_magic(reader);
        self.read_and_check_version(reader);
        let cp = ConstantPool::read_constant_poll(reader);
        self.constant_pool = Some(cp.clone());
        self.access_flags = reader.read_u16();
        self.this_class = reader.read_u16();
        self.super_class = reader.read_u16();
        self.interfaces = reader.read_u16s();
        self.fields = MemberInfo::read_members(reader, cp.clone());
        self.methods = MemberInfo::read_members(reader, cp.clone());
        self.attributes = attribute_info::read_attributes(reader, cp)
    }
    
    // 校验魔数
    fn read_and_check_magic(&self, reader: &mut ClassReader) {
        let magic = reader.read_u32();
        if magic != 0xCAFEBABE {
            panic!("java.lang.ClassFormatError: magic!")
        }
    }

    // 版本号,支持45.x, 46.0-52.0
    fn read_and_check_version(&mut self, reader: &mut ClassReader) {
        self.minor_version = reader.read_u16();
        self.major_version = reader.read_u16();
        if self.major_version == 45{
            return;
        }
        if 46 <= self.major_version && self.major_version <= 52 && self.minor_version == 0 {
            return;
        }
        panic!("java.lang.UnsupportedClassVersionError!")
    }

    // pub fn minor_version(&self) -> u16 {
    //     self.minor_version
    // }

    // pub fn major_version(&self) -> u16 {
    //     self.major_version
    // }

    pub fn constant_pool(&self) -> Rc<RefCell<ConstantPool>> {
        self.constant_pool.as_ref().unwrap().clone()
    }

    pub fn access_flags(&self) -> u16 {
        self.access_flags
    }

    pub fn filds(&self) -> &Vec<MemberInfo> {
        &self.fields
    }

    pub fn methods(&self) -> &Vec<MemberInfo> {
        &self.methods
    }

    // 常量池查找类名
    pub fn class_name(&self) -> String {
        self.constant_pool().borrow().get_class_name(self.this_class as usize)
    }

    // 常量池查找类名
    pub fn super_class_name(&self) -> String {
        if self.super_class > 0 {
            self.constant_pool().borrow().get_class_name(self.super_class as usize)
        } else {
            "".into()
        }
    }

    // 常量池查找类名
    pub fn interface_names(&self) -> Vec<String> {
        let cp = self.constant_pool();
        self.interfaces.iter()
            .map(|cp_index| cp.borrow().get_class_name(*cp_index as usize))
            .collect()
    }

    pub fn source_file_attribute(&self) -> Option<&SourceFileAttribute> {
        for attr_info in &self.attributes {
            if let Attribute::SourceFileAttribute(info) = attr_info {
                return Some(info);
            }
        }
        None
    }

    pub fn bootstrap_methods(&self) -> Option<BootstrapMethodsAttribute> {
        // TODO 231108 暂用clone后面试试能否直接传递所有权。
        for attr_info in &self.attributes {
            if let Attribute::BootstrapMethodsAttribute(info) = attr_info {
                return Some(info.clone());
            }
        }
        None
    }

    pub fn enclosing_method(&self) -> Option<EnclosingMethodAttribute> {
        // TODO 231114 暂用clone后面试试能否直接传递所有权。
        for attr_info in &self.attributes {
            if let Attribute::EnclosingMethodAttribute(info) = attr_info {
                return Some(info.clone());
            }
        }
        None
    }

    

}